package de.mmis.core.base.gclass;

import java.util.Arrays;
import java.util.List;

/**
 * {@link GClass} representing a java class, (possibly with generic parameters)
 * 
 * @author Christian Koch
 * 
 */
public class GParameterized extends GClass {
	private Class<?> clazz; // base class of this GClass
	private GClass[] typeParameters;// type parameters of this GClass

	/**
	 * creates new GParameterized instance with specified base class and
	 * parameters
	 * 
	 * @param clazz
	 *            base class of this instance
	 * @param typeParameters
	 *            array of type parameters of this instance
	 */
	public GParameterized(Class<?> clazz, GClass[] typeParameters) {
		this.clazz = clazz;
		this.typeParameters = typeParameters;
	}

	/**
	 * set base class of this type
	 * 
	 * @param clazz
	 *            new base class
	 */
	public void setBaseClass(Class<?> clazz) {
		this.clazz = clazz;
	}

	/**
	 * @return array of type parameters of this type
	 */
	public GClass[] getTypeParameterClass() {
		return this.typeParameters;
	}

	public void setTypeParameterClass(GClass[] typeParameters) {
		this.typeParameters = typeParameters;
	}

	@Override
	protected void toStringInternal(StringBuilder sb) {
		sb.append(this.clazz.getName());
		if (this.typeParameters.length > 0) {
			sb.append("<");
			for (int i = 0; i < this.typeParameters.length; i++) {
				if (i > 0)
					sb.append(",");
				this.typeParameters[i].toStringInternal(sb);
			}
			sb.append(">");
		}
	}

	@Override
	public boolean equalsClass(Class<?> c) {
		return c == this.clazz;
	}

	@Override
	public Class<?> getBaseClass() {
		return this.clazz;
	}

	@Override
	protected void collectClasses(List<Class<?>> classList) {
		classList.add(this.clazz);
		for (GClass gc : this.typeParameters)
			gc.collectClasses(classList);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((clazz == null) ? 0 : clazz.hashCode());
		result = prime * result + Arrays.hashCode(typeParameters);
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		GParameterized other = (GParameterized) obj;
		if (clazz == null) {
			if (other.clazz != null)
				return false;
		} else if (!clazz.equals(other.clazz))
			return false;
		if (!Arrays.equals(typeParameters, other.typeParameters))
			return false;
		return true;
	}
}
